package com.yong.android.framework.view.recyclerview;

import android.content.Context;
import android.support.annotation.CallSuper;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.ViewGroup;


import com.yong.android.framework.view.adapter.ViewHolderLifecycle;

import java.util.ArrayList;
import java.util.List;


/**
 * Description: 灵活的cell RecyclerView 适配器,支持状态视图，上拉刷新等操作
 *
 * Description:
 * Author:yong
 * Date:2017-12-21
 */

public class CellListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private static final String TAG = "CellListAdapter";
    private SparseArray<String> viewTypeCache = new SparseArray<>();
    private List<RecyclerViewCell> cellList = new ArrayList<>();
    private RecyclerView mRecyclerView;
    private StatusCell mStatusCell;
    private LoadingMoreCell mLoadMoreCell;
    private LayoutInflater mInflater;
    private RecyclerView.LayoutManager mLayoutManager;

    List<RecyclerView.ItemDecoration> mItemDecorations = new ArrayList<>();
    boolean isRemoveDecorations = false;

    public CellListAdapter(Context context) {
        mInflater = LayoutInflater.from(context);
    }

    @Override
    public final RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (isStatusEnable()) {
            return mStatusCell.onCreateViewHolder(mInflater, parent, viewType);
        }
        if (isLoadMoreEnable() && viewType == getFooterViewType(mLoadMoreCell.getViewType())) {
            return mLoadMoreCell.onCreateViewHolder(mInflater, parent, mLoadMoreCell.getViewType());
        }
        for (int i = 0; i < cellList.size(); i++) {
            RecyclerViewCell cell = cellList.get(i);
            if ((Math.abs(viewType) & 0xFFFFFF80) == viewTypeCache.keyAt(viewTypeCache.indexOfValue(cell.name))) {
                return cell.onCreateViewHolder(mInflater, parent, viewType & 0x0000007F);
            }

        }
        return null;
    }

    @SuppressWarnings("unchecked")
    @Override
    public final void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (isStatusEnable()) {
            mStatusCell.onBindViewHolder(holder, position);
            return;
        }
        if (isLoadMoreEnable() && position == getItemCount() - 1) {
            mLoadMoreCell.onBindViewHolder(holder);
            return;
        }

        int tCount = 0;
        for (int i = 0; i < cellList.size(); i++) {
            tCount += cellList.get(i).getCount();
            if (position < tCount) {
                RecyclerViewCell cell = cellList.get(i);
                int subCount = cell.getCount();
                int preCount = tCount - subCount;
                cell.onBindViewHolder(holder, (position - preCount) % subCount);
                break;
            }
        }

    }

    @Override
    public final int getItemCount() {
        if (isStatusEnable()) {
            return mStatusCell.getCount();
        }
        int count = getTotalCount();
        if (isLoadMoreEnable()) {
            count += 1;
        }
        return count;
    }

    @Override
    public final int getItemViewType(int position) {
        int viewType = -1;
        if (isStatusEnable()) {
            viewType = getStatusViewType(mStatusCell.getItemViewType(position));
        } else if (isLoadMoreEnable() && position == getItemCount() - 1) {

            viewType = getFooterViewType(mLoadMoreCell.getViewType());
        } else {
            viewType = getCellViewType(position);
        }
        return viewType;
    }

    @CallSuper
    @Override
    public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
        if (holder instanceof ViewHolderLifecycle) {
            ((ViewHolderLifecycle) holder).onViewAttachedToWindow();
        }
    }

    @CallSuper
    @Override
    public void onViewDetachedFromWindow(RecyclerView.ViewHolder holder) {
        if (holder instanceof ViewHolderLifecycle) {
            ((ViewHolderLifecycle) holder).onViewDetachedFromWindow();
        }
    }

    @Override
    public final void onAttachedToRecyclerView(RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        mRecyclerView = recyclerView;

        RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
        if (layoutManager != null) {
            if (mLayoutManager == null || mLayoutManager != layoutManager) {
                setLayoutManager(layoutManager, false);
            }
        } else {
            if (mLayoutManager != null) {
                setLayoutManager(mLayoutManager);
            }
        }

        if (mLoadMoreCell != null) {
            mLoadMoreCell.onAttachedToRecyclerView(recyclerView);
        }
        if (mStatusCell != null) {
            mStatusCell.mRecyclerView = recyclerView;
        }

        if (isStatusEnable()) {
            notifyChangedDataItemDecoration(true);
        }
    }

    @Override
    public final void onDetachedFromRecyclerView(RecyclerView recyclerView) {
        super.onDetachedFromRecyclerView(recyclerView);

        if (mLoadMoreCell != null) {
            mLoadMoreCell.onDetachedFromRecyclerView(recyclerView);
        }
        if (mStatusCell != null) {
            mStatusCell.mRecyclerView = null;
        }

        notifyChangedDataItemDecoration(true);

        mRecyclerView = null;

    }


    public final int getTotalCount() {
        int totalCount = 0;
        for (int i = 0; i < cellList.size(); i++) {
            totalCount += cellList.get(i).getCount();
        }

        return totalCount;
    }

    public final void setLayoutManager(@NonNull RecyclerView.LayoutManager layoutManager) {
        setLayoutManager(layoutManager, true);
    }

    /**
     * fixme onAttachedToRecyclerView 导致RecyclerView未正确显示，修复用户自己自定义GridLayoutManager导致框架配置失效的问题
     *
     * @param layoutManager
     * @param setupRecyclerView
     */
    private void setLayoutManager(@NonNull RecyclerView.LayoutManager layoutManager, boolean setupRecyclerView) {
        this.mLayoutManager = layoutManager;
        if (mLayoutManager instanceof GridLayoutManager) {
            ((GridLayoutManager) mLayoutManager).setSpanSizeLookup(new DefaultSpanSizeLookup());
        }

        if (setupRecyclerView && mRecyclerView != null) {
            mRecyclerView.setLayoutManager(layoutManager);
        }
    }

    public final void addItemDecoration(RecyclerView.ItemDecoration itemDecoration) {
        mItemDecorations.add(itemDecoration);
        if (mRecyclerView != null) {
            mRecyclerView.addItemDecoration(itemDecoration);
        }
    }

    void notifyChangedDataItemDecoration(boolean isRemove) {
        if (isRemove) {
            if (!isRemoveDecorations) {
                if (mRecyclerView != null) {
                    for (RecyclerView.ItemDecoration itemDecoration : mItemDecorations) {
                        mRecyclerView.removeItemDecoration(itemDecoration);
                    }
                    isRemoveDecorations = true;
                }
            }
        } else {
            if (isRemoveDecorations) {
                if (mRecyclerView != null) {
                    for (RecyclerView.ItemDecoration itemDecoration : mItemDecorations) {
                        mRecyclerView.addItemDecoration(itemDecoration);
                    }
                    isRemoveDecorations = false;
                }
            }
        }
    }

    public final void setStatusCell(@NonNull StatusCell statusCell) {
        if (mStatusCell != null) {
            mStatusCell.mRecyclerView = null;
            mStatusCell.mHostAdapter = null;
        }
        mStatusCell = statusCell;
        mStatusCell.mHostAdapter = this;
        if (mRecyclerView != null) {
            mStatusCell.mRecyclerView = mRecyclerView;
        }
    }

    public final void setLoadMoreCell(@NonNull LoadingMoreCell loadMoreCell) {
        if (mLoadMoreCell != null) {
            if (mRecyclerView != null) {
                mLoadMoreCell.onDetachedFromRecyclerView(mRecyclerView);
            }
            mLoadMoreCell.mHostAdapter = null;
        }
        mLoadMoreCell = loadMoreCell;
        if (mRecyclerView != null) {
            mLoadMoreCell.onAttachedToRecyclerView(mRecyclerView);
        }
        mLoadMoreCell.mHostAdapter = this;
    }

    public final void addCell(RecyclerViewCell cell) {
        addCell(cell, cell.getClass().getName());
    }

    public final void addCell(RecyclerViewCell cell, String cellName) {
        if (viewTypeCache.indexOfValue(cellName) == -1) {
            viewTypeCache.put((viewTypeCache.size() + 1) << 7, cellName);
        }
        cellList.add(cell);
        cell.mHostAdapter = this;
        cell.name = cellName;
    }

    public final RecyclerViewCell getCellAt(int position) {
        return cellList.get(position);
    }

    public final void removeCell(RecyclerViewCell cell) {
        cellList.remove(cell);
        cell.mHostAdapter = null;
    }

    public final void removeAllCell() {
        for (int i = 0; i < cellList.size(); i++) {
            cellList.get(i).mHostAdapter = null;
        }
        cellList.clear();
    }

    public final int cellIndexOf(RecyclerViewCell cell) {
        return cellList.indexOf(cell);
    }

    public final int findCellPosition(RecyclerViewCell cell) {
        if (cell.getCount() == 0) {
            return -1;
        }
        int cellPosition = cellIndexOf(cell);
        if (cellPosition == -1) {
            return -1;
        }
        int position = -1;
        for (int i = 0; i < cellPosition + 1; i++) {
            if (cell.getCount() != 0) {
                position++;
            }
        }
        return position;
    }

    int findCellAdapterPosition(RecyclerViewCell cell) {
        if (cell.getCount() == 0) {
            return -1;
        }
        int cellPosition = cellIndexOf(cell);
        if (cellPosition == -1) {
            return -1;
        }
        int count = 0;
        for (int i = 0; i < cellPosition; i++) {
            count += cellList.get(i).getCount();
        }
        return count;
    }

    boolean isStatusEnable() {
        return mStatusCell != null && mStatusCell.isEnable;
    }

    public final boolean isLoadMoreEnable() {
        return mLoadMoreCell != null && mLoadMoreCell.isEnable;
    }

    private int getStatusViewType(@IntRange(from = -31, to = 31) int viewType) {
        if (viewType < 0) {
            return -(1 << 5 + Math.abs(viewType));
        }
        return 1 << 5 + viewType;
    }

    private int getFooterViewType(@IntRange(from = -31, to = 31) int viewType) {
        if (viewType < 0) {
            return -(3 << 4 + Math.abs(viewType));
        }
        return 3 << 4 + viewType;
    }

    private int getCellViewType(int position) {

        int tCount = 0;
        for (int i = 0; i < cellList.size(); i++) {
            tCount += cellList.get(i).getCount();
            if (position < tCount) {
                RecyclerViewCell cell = cellList.get(i);
                int subCount = cell.getCount();
                int preCount = tCount - subCount;
                int viewType = cell.getItemViewType((position - preCount) % subCount);
                if (viewType < 0) {
                    return -(viewTypeCache.keyAt(viewTypeCache.indexOfValue(cell.name)) + Math.abs(viewType));
                } else {
                    return viewTypeCache.keyAt(viewTypeCache.indexOfValue(cell.name)) + viewType;
                }

            }
        }
        return -(1 << 5);
    }

    private class DefaultSpanSizeLookup extends GridLayoutManager.SpanSizeLookup {

        @Override
        public int getSpanSize(int position) {
            if (isStatusEnable()) {
                return mStatusCell.getSpan(((GridLayoutManager) mLayoutManager).getSpanCount(), position);
            }
            if (cellList == null || cellList.size() == 0) {
                return 0;
            } else {
                int totalSpan = ((GridLayoutManager) mLayoutManager).getSpanCount();
                if (isLoadMoreEnable() && position == getItemCount() - 1) {
                    return totalSpan;
                }
                int span = 1;
                int tCount = 0;
                for (int i = 0; i < cellList.size(); i++) {
                    tCount += cellList.get(i).getCount();
                    if (position < tCount) {
                        RecyclerViewCell cell = cellList.get(i);
                        int subCount = cell.getCount();
                        int preCount = tCount - subCount;
                        span = cell.getSpan(totalSpan, (position - preCount) % subCount);
                        break;
                    }
                }

                return span > totalSpan ? 0 : span;
            }
        }
    }



}
